package gov.pbc.nn.kjgl.webService.endpoint;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.jws.soap.SOAPBinding;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.soap.MTOM;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.DocumentSource;
import org.dom4j.tree.BaseElement;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.oxm.mime.MimeContainer;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.PayloadEndpoint;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.support.DefaultStrategiesHelper;
import org.springframework.ws.support.MarshallingUtils;
import org.springframework.ws.transport.WebServiceMessageReceiver;
import org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport;

import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.orm.ParseResult;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.bdf2.core.service.IDeptService;
import com.bstek.bdf2.webservice.jaxb.IWebservice;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.core.Configure;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.bdf.service.UserService.DefaultUserRowMapper;
import gov.pbc.nn.core.dao.AbstractHibernateDao;
import gov.pbc.nn.core.dao.PbcnnCoreJdbcDao;
import gov.pbc.nn.kjgl.task.entity.TaskEntity;
import gov.pbc.nn.kjgl.task.entity.TaskHandleFile;

@Endpoint
@SOAPBinding(style = SOAPBinding.Style.RPC)
@MTOM // 开启MTOM功能
public class taskEndpoint extends AbstractHibernateDao implements IWebservice {
	public final static String namespace = "OAToTask";
	public final static String ftpUserName = "root";
	public final static String ftpPassword = "111111";

	@Resource(name = PbcnnCoreJdbcDao.BEAN_ID)
	private PbcnnCoreJdbcDao jdbcDao;
	
	@Autowired
	@Qualifier(IDeptService.BEAN_ID)
	private IDeptService deptService;

	private Map<String, Object> getUserInfo(String cname) {

		String sql = "SELECT\n" + "	T.*\n" + "FROM\n" + "	(\n" + "		SELECT\n"
				+ "			U.*, D.ID_ AS DEPT_ID_,D.NAME_ AS DEPT_NAME_\n" + "		FROM\n" + "			t_user U\n"
				+ "		LEFT JOIN bdf2_user_dept UD ON U.USERNAME_ = UD.USERNAME_\n"
				+ "		LEFT JOIN t_dept D ON UD.DEPT_ID_ = D.ID_ order by D.ID_,U.USERNAME_\n" + "	) T\n" + "WHERE\n"
				+ "	T.CNAME_ = ? ";
		List<Map<String, Object>> rs =jdbcDao.getJdbcTemplate().queryForList(sql, new Object[] { cname });
		if(rs!=null&&rs.isEmpty()==false)
			return rs.get(0);
		else return null;
	}

	@SuppressWarnings("unchecked")
	@PayloadRoot(localPart = "taskRequest", namespace = taskEndpoint.namespace)
	@DataProvider
	@DataResolver
	@Transactional
	public @ResponsePayload void taskAction(@RequestPayload MessageContext messageContext) throws Exception {
		Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
		final taskResponse response = new taskResponse();
		try {
			marshaller.setClassesToBeBound(new Class[] { taskRequest.class, taskResponse.class, });
			marshaller.setMtomEnabled(true);
			final taskRequest request = (taskRequest) MarshallingUtils.unmarshal(marshaller, messageContext.getRequest());
			final Map<String, Object> userInfo = this.getUserInfo(request.getTaskUser());
			if (userInfo == null) {
				response.setSuccessful(false);
				response.setErrorInfo("综合业务系统未找到用户【" + request.getTaskUser() + "】的信息！");
			} else {
				Dept dept = (Dept) deptService.loadDeptById(userInfo.get("DEPT_ID_").toString());
				final Dept CDept = (Dept) dept.getCDept();
				String result = this.doInHibernateSession(new ISessionCallback<String>() {
					@Override
					public String doInSession(Session session) {
						// TODO Auto-generated method stub
						JtaTransactionManager jta = ContextHolder.getBean("bdf2.transactionManager");
						UserTransaction ut = jta.getUserTransaction();//分布式事务
						try {
							ut.begin();
							TaskEntity taskEntity = new TaskEntity();
							taskEntity.setCreateDate(new Date());
							taskEntity.setCreateUser(userInfo.get("USERNAME_").toString());
							taskEntity.setCreateUserCname(userInfo.get("CNAME_").toString());
							taskEntity.setName(request.getTitle() + "（" + request.getDocumentMark() + "）");
							taskEntity.setDeptName(CDept.getName());
							taskEntity.setDeptId(CDept.getId());
							taskEntity.setRemark(request.toString());
							taskEntity.setTaskType("NN");
							taskEntity.setStartDate(new Date());
							taskEntity.setNeedBranch(true);
							session.save(taskEntity);
							if (request.getAttachments() != null && request.getAttachments().isEmpty() == false) {
								Path path = Paths.get(Configure.getString("TASK_FILE_UPLOAD_PATH"), "/HandleFile");
								Files.createDirectories(path);
								for (attachment file : request.getAttachments()) {
									File destFile = Files.createFile(path.resolve(UUID.randomUUID().toString())).toFile();
									FileOutputStream fos = new FileOutputStream(destFile);
									/*
									 * DataHandler dataHandler =
									 * file.getAttachmentData(); InputStream is
									 * = dataHandler.getInputStream(); byte[]
									 * bytes = new byte[1024 * 1024]; int len =
									 * 0; while ((len = is.read(bytes)) != -1) {
									 * fos.write(bytes, 0, len); } is.close();
									 */
									// System.out.println(new
									// String(file.getAttachmentURL().getBytes("utf8"),"iso-8859-1"));
									String ftpPath = new String(file.getAttachmentURL().getBytes("utf8"), "iso-8859-1").substring(file.getAttachmentURL().indexOf("//") + 2);
									String ftpHost = ftpPath.substring(0, ftpPath.indexOf('/'));
									String ftpDirectory = ftpPath.substring(ftpPath.indexOf('/') + 1, ftpPath.lastIndexOf('/'));
									String ftpFileName = ftpPath.substring(ftpPath.lastIndexOf('/') + 1);
									FTPClient ftpClient = new FTPClient();
									ftpClient.connect(ftpHost);
									ftpClient.login(ftpUserName, ftpPassword);
									ftpClient.enterLocalPassiveMode();
									ftpClient.setBufferSize(1024 * 1024);
									// 设置文件类型（二进制）
									ftpClient.changeWorkingDirectory(ftpDirectory);
									ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
									// boolean
									// ftpResult=ftpClient.retrieveFile(new
									// String(ftpFileName.getBytes("utf8"),"iso-8859-1"),
									// fos);
									boolean ftpResult = ftpClient.retrieveFile(ftpFileName, fos);
									fos.flush();
									fos.close();
									if (ftpResult == false) {
										return "从ftp下载文件：" + file.getAttachmentName() + "  失败！";
									}
									TaskHandleFile taskHandleFile = new TaskHandleFile();
									taskHandleFile.setCreateDate(new Date());
									taskHandleFile.setCreateUser(userInfo.get("USERNAME_").toString());
									taskHandleFile.setCreateUserCname(userInfo.get("CNAME_").toString());
									taskHandleFile.setTaskEntityId(taskEntity.getId());
									taskHandleFile.setFileName(file.getAttachmentName());
									taskHandleFile.setPath(destFile.getAbsolutePath());
									session.save(taskHandleFile);
								}
							}
							ut.commit();
							return "";
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							try {
								ut.rollback();
							} catch (IllegalStateException | SecurityException | SystemException e1) {
								// TODO Auto-generated catch block
								e1.printStackTrace();
							}
							session.clear();// 不清空session，回滚失败。
							return e.getMessage();
						}
					}
				});
				response.setSuccessful(StringUtils.isBlank(result) ? true : false);
				response.setErrorInfo(result);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			response.setSuccessful(false);
			response.setErrorInfo(e.getMessage());
		}
		DefaultStrategiesHelper strategiesHelper = new DefaultStrategiesHelper(WebServiceTemplate.class);
		WebServiceMessageFactory messageFactory = (WebServiceMessageFactory) strategiesHelper.getDefaultStrategy(WebServiceMessageFactory.class);
		SaajSoapMessage message = (SaajSoapMessage) messageFactory.createWebServiceMessage();
		MarshallingUtils.marshal(marshaller, response, message);
		messageContext.setResponse(message);
	}

	@Override
	public Class<?>[] bindClasses() {
		// TODO Auto-generated method stub
		return new Class[] { taskRequest.class, taskResponse.class };
	}

	@Override
	public boolean useSecurity() {
		// TODO Auto-generated method stub
		return false;
	}
}
